using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Microsoft.AspNet.Identity;
using SingleUserMall.Actives;
using SingleUserMall.Authorization.Users;
using SingleUserMall.Commissions;
using SingleUserMall.Common;
using SingleUserMall.Orders;
using SingleUserMall.Points;
using SingleUserMall.Sms;
using SingleUserMall.Users.Form;
using SingleUserMall.Users.VO;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace SingleUserMall.Users
{
    public class UserAppService : SingleUserMallAppServiceBase, IUserAppService
    {
        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<Order, long> _orderRepository;
        private readonly IRepository<UserCommission, long> _userCommissionRepository;
        private readonly IRepository<UserCash, long> _userCashRepository;
        private readonly IRepository<UserSale, long> _userSaleRepository;
        private readonly IRepository<UserRefit, long> _userRefitRepository;
        private readonly IRepository<UserPromotion, long> _userPromotionRepository;
        private readonly IRepository<UserShare, long> _userShareRepository;
        private readonly IRepository<UserFavorite, long> _userFavoriteRepository;
        private readonly IRepository<UserCard, long> _userCardRepository;
        private readonly IRepository<UserWalletDetail, long> _userWalletDetailRepository;
        private readonly IRepository<UserRedPacketDetail, long> _userRedPacketDetailRepository;
        private readonly IRepository<SmsEntity, long> _smsRepository;
        private readonly IRepository<UserPoints, long> _userPointsRepository;
        private readonly IRepository<Active, long> _activeRepository;
        private readonly IRepository<ActiveRecord, long> _activeRecordRepository;
        public UserAppService(
            IRepository<User, long> userRepository,
            IRepository<Order, long> orderRepository,
            IRepository<UserCommission, long> userCommissionRepository,
            IRepository<UserCash, long> userCashRepository,
            IRepository<UserSale, long> userSaleRepository,
            IRepository<UserRefit, long> userRefitRepository,
            IRepository<UserPromotion, long> userPromotionRepository,
            IRepository<UserShare, long> userShareRepository,
            IRepository<UserFavorite, long> userFavoriteRepository,
            IRepository<UserCard, long> userCardRepository,
            IRepository<UserWalletDetail, long> userWalletDetailRepository,
            IRepository<UserRedPacketDetail, long> userRedPacketDetailRepository,
            IRepository<SmsEntity, long> smsRepository,
            IRepository<UserPoints, long> userPointsRepository,
            IRepository<Active, long> activeRepository,
            IRepository<ActiveRecord, long> activeRecordRepository

            )
        {
            _userRepository = userRepository;
            _orderRepository = orderRepository;
            _userCommissionRepository = userCommissionRepository;
            _userCashRepository = userCashRepository;
            _userSaleRepository = userSaleRepository;
            _userRefitRepository = userRefitRepository;
            _userPromotionRepository = userPromotionRepository;
            _userShareRepository = userShareRepository;
            _userFavoriteRepository = userFavoriteRepository;
            _userCardRepository = userCardRepository;
            _userWalletDetailRepository = userWalletDetailRepository;
            _userRedPacketDetailRepository = userRedPacketDetailRepository;
            _smsRepository = smsRepository;
            _userPointsRepository = userPointsRepository;
            _activeRepository = activeRepository;
            _activeRecordRepository = activeRecordRepository;
        }

        [AbpAuthorize]
        public async Task CashAsync(UserCashForm form)
        {
            var user = await UserManager.GetUserByIdAsync(AbpSession.GetUserId());
            if (form.CashType == CashType.Commision)
            {
                if (user.Commision < form.Amount)
                {
                    throw new UserFriendlyException("个人佣金金额不够");
                }
            }

            if (form.CashType == CashType.RedPacket)
            {
                if (user.UserRedPacket < form.Amount)
                {
                    throw new UserFriendlyException("个人红包金额不够");
                }
            }

            if (form.CashType == CashType.CanUsePoint)
            {
                if (user.CanUsePoints < form.Amount)
                {
                    throw new UserFriendlyException("个人可提现体验金不够");
                }
            }

            if (_userCashRepository.Count(x => x.UserId == user.Id && x.VerifyStatus == UserCashVerifyStatus.WaitAudit) > 0)
            {
                throw new UserFriendlyException("您还有正在审核的提现申请，暂时不能提现");
            }

            await _userCashRepository.InsertAndGetIdAsync(new UserCash
            {
                Amount = form.Amount,
                CardName = form.CardName,
                CardNumber = form.CardNumber,
                BankName = form.BankName,
                BankCode = form.BankCode,
                UserId = AbpSession.GetUserId(),
                OrderNo = Functions.NewOrderNo(),
                CashType = form.CashType,
                VerifyStatus = UserCashVerifyStatus.WaitAudit
            });
        }

        public async Task<ListResultDto<BankVO>> GetBanksAsync()
        {
            var list = new List<BankVO>
            {
                new BankVO{
                    BankCode = "1002",
                    BankName = "工商银行",
                },new BankVO{
                    BankCode = "1005",
                    BankName = "农业银行",
                },new BankVO{
                    BankCode = "1026",
                    BankName = "中国银行",
                },new BankVO{
                    BankCode = "1003",
                    BankName = "建设银行",
                },new BankVO{
                    BankCode = "1001",
                    BankName = "招商银行",
                },new BankVO{
                    BankCode = "1066",
                    BankName = "邮储银行",
                },new BankVO{
                    BankCode = "1020",
                    BankName = "交通银行",
                },new BankVO{
                    BankCode = "1004",
                    BankName = "浦发银行",
                },new BankVO{
                    BankCode = "1006",
                    BankName = "民生银行",
                },new BankVO{
                    BankCode = "1009",
                    BankName = "兴业银行",
                },new BankVO{
                    BankCode = "1010",
                    BankName = "平安银行",
                },new BankVO{
                    BankCode = "1021",
                    BankName = "中信银行",
                },new BankVO{
                    BankCode = "1025",
                    BankName = "华夏银行",
                },new BankVO{
                    BankCode = "1027",
                    BankName = "广发银行",
                },new BankVO{
                    BankCode = "1022",
                    BankName = "光大银行",
                },new BankVO{
                    BankCode = "1032",
                    BankName = "北京银行",
                },new BankVO{
                    BankCode = "1056",
                    BankName = "宁波银行",
                },
            };
            return await Task.FromResult(new ListResultDto<BankVO> { Items = list });
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserVO>> GetSpreadUsersAsync(SpreadPagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var spreadUserQuery = _userRepository.GetAll()
                .WhereIf(form.Level == SpreadLevel.Source, x => x.SourceUserId == userId)
                .WhereIf(form.Level == SpreadLevel.Grand, x => x.GrandUserId == userId)
                .OrderByDescending(x => x.CreationTime);
            return await spreadUserQuery.ToPagedResultDtoAsync<User, UserVO>(form);
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserVO>> GetAllCanSendUsersAsync(SimpleUserSearchForm form)
        {
            var userId = AbpSession.GetUserId();
            var spreadUserQuery = _userRepository.GetAll()
                .Where(x=> x.Id != 1 && x.IsActive)
                .WhereIf(!string.IsNullOrEmpty(form.KeyWords), x=> x.UserName.Contains(form.KeyWords) || x.PhoneNumber.Contains(form.KeyWords) || x.Name.Contains(form.KeyWords))
                .OrderByDescending(x => x.CreationTime);
            return await spreadUserQuery.ToPagedResultDtoAsync<User, UserVO>(form);
        }

        [AbpAuthorize]
        public async Task<ListResultDto<UserCardVO>> GetUserCardsAsync()
        {
            var userId = AbpSession.GetUserId();
            var query = _userCardRepository.GetAll().Where(x => x.UserId == userId)
                .OrderByDescending(x => x.CreationTime);
            return await query.ToListResultDtoAsync<UserCard, UserCardVO>();
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserCashVO>> GetUserCashesAsync(UserCashPagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var userCashesQuery = _userCashRepository.GetAll().Where(x => x.UserId == userId)
                .WhereIf(form.CashType.HasValue, x => x.CashType == form.CashType)
                .OrderByDescending(x => x.CreationTime);
            return await userCashesQuery.ToPagedResultDtoAsync<UserCash, UserCashVO>(form);
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserCommissionVO>> GetUserCommisionsAsync(UserCommissionPagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var userCommisionsQuery = _userCommissionRepository.GetAll().Where(x => x.UserId == userId)
               .WhereIf(form.CommissionType.HasValue, x => x.CommissionType == form.CommissionType)
                .OrderByDescending(x => x.CreationTime);
            return await userCommisionsQuery.ToPagedResultDtoAsync<UserCommission, UserCommissionVO>(form, (c, vo) =>
            {
                vo.inFromUser = _userRepository.FirstOrDefault(c.FromUserId);

            });
        }
        [AbpAuthorize]
        public async Task<InComeVO> GetUserCommisionAsync()
        {
            var userId = AbpSession.GetUserId();
            var user = await _userRepository.FirstOrDefaultAsync(userId);
            var userCommisionsQuery = _userCommissionRepository.GetAll().OrderByDescending(x => x.CreationTime);
            var userCommisions = await _userCommissionRepository.FirstOrDefaultAsync(x => x.UserId == userId);
            var yesterday = DateTime.Now.AddDays(-1);
            var todayIncome = _userCommissionRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(DateTime.Now)).Sum(x => (decimal?)x.Amount);
            var yesterdayIncome = _userCommissionRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday)).Sum(x => (decimal?)x.Amount);
            var sumIncome = _userCommissionRepository.GetAll().Where(x => x.UserId == userId).Sum(x => (decimal?)x.Amount);
            return userCommisions.ToVO<UserCommission, InComeVO>((c, vo) =>
            {

                vo.inFromUser = _userRepository.FirstOrDefault(c.FromUserId);
                vo.Amount = user.Commision;
                vo.TodayIncome = todayIncome ?? 0;
                vo.YesterdayIncome = yesterdayIncome ?? 0;
                vo.SumIncome = sumIncome ?? 0;
            });
        }

        [AbpAuthorize]
        public async Task<ProfitVO> GetUserProfit()
        {
            var userId = AbpSession.GetUserId();
            var user = await _userRepository.FirstOrDefaultAsync(userId);
            var today = DateTime.Now;
            var yesterday = DateTime.Now.AddDays(-1);
            var todayFHProfit = _userCommissionRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(today) && x.CommissionType == Commission.CommissionType.TreeShopping).Sum(x => (decimal?)x.Amount);
            var yesterdayFHProfit = _userCommissionRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday) && x.CommissionType == Commission.CommissionType.TreeShopping).Sum(x => (decimal?)x.Amount);
            var allFHProfit = _userCommissionRepository.GetAll().Where(x => x.UserId == userId && x.CommissionType == Commission.CommissionType.TreeShopping).Sum(x => (decimal?)x.Amount);
            var allCapital = _orderRepository.GetAll().Where(x => x.UserId == userId && x.Status >= OrderStatus.Paid && x.ShoppingCartType == ShoppingCarts.ShoppingCartType.TreeShopping && !x.OrderDetails.FirstOrDefault().IsRefund).Sum(x => (decimal?)x.ActualAmount);
            var todayShareProfit = _userPointsRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(today) && x.Type == UserPointsType.KYTYJ).Sum(x => (decimal?)x.Points);
            var yesterdayShareProfit = _userPointsRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday) && x.Type == UserPointsType.KYTYJ).Sum(x => (decimal?)x.Points);
            var allShareProfit = user.CanUsePoints;
            var todayQMProfit = _userPointsRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(today) && x.Type == UserPointsType.TYJ).Sum(x => (decimal?)x.Points);
            var yesterdayQMProfit = _userPointsRepository.GetAll().Where(x => x.UserId == userId && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday) && x.Type == UserPointsType.TYJ).Sum(x => (decimal?)x.Points);
            var allQMProfit = user.Points;
            var canCashAmount = user.Commision + user.CanUsePoints;
            decimal yesterdayAllProfit = yesterdayFHProfit??0 + yesterdayShareProfit??0 + yesterdayQMProfit??0;
            decimal todayAllProfit = todayFHProfit??0 + todayShareProfit??0 + todayQMProfit??0;
            decimal allProfit = allFHProfit??0 + allShareProfit + allQMProfit;
            ProfitVO profit = new ProfitVO
            {
                TodayFHProfit = todayFHProfit ?? 0,
                YesterdayFHProfit = yesterdayFHProfit ?? 0,
                AllFHProfit = allFHProfit ?? 0,
                AllCapital = allCapital ?? 0,
                TodayShareProfit = todayShareProfit ?? 0,
                YesterdayShareProfit = yesterdayShareProfit ?? 0,
                AllShareProfit = allShareProfit,
                TodayQMProfit = todayQMProfit ?? 0,
                YesterdayQMProfit = yesterdayQMProfit ?? 0,
                AllQMProfit = allQMProfit,
                CanCashAmount = canCashAmount,
                YesterdayAllProfit = yesterdayAllProfit,
                TodayAllProfit = todayAllProfit,
                AllProfit = allProfit
            };
            return await Task.FromResult(profit);
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserPointsVO>> GetUserPointsAsync(UserAppPointPagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var query = _userPointsRepository.GetAll().Where(x=> x.UserId == userId && x.Type == form.UserPointsType)
                .WhereIf(form.UserPointsStatus.HasValue, x => x.Status == form.UserPointsStatus)
                .OrderByDescending(x => x.CreationTime).ThenBy(x => x.Type);
            return await query.ToPagedResultDtoAsync<UserPoints, UserPointsVO>(form, (v, vo) =>
            {
                vo.inFromUser = _userRepository.FirstOrDefault(v.FromUserId);
                vo.inUser = v.User;
            });
        }


        [AbpAuthorize]
        public async Task<UserMiniVO> GetUserInfoAsync()
        {
            var userId = AbpSession.GetUserId();
            var user = await _userRepository.FirstOrDefaultAsync(userId);
            var userManagerName = "";
            if (user.ManagerUserId.HasValue)
            {
                var managerUser = await _userRepository.FirstOrDefaultAsync(user.ManagerUserId.Value);
                userManagerName = managerUser.UserName;
            }
            var orderQuery = _orderRepository.GetAll().Where(x => x.UserId == userId && x.OrderType == OrderType.Shopping);
            var sourceUserQty = await _userRepository.CountAsync(x => x.SourceUserId == user.Id);
            return user.ToVO<User, UserMiniVO>((u, vo) =>
            {
                vo.WaitPayCount = orderQuery.Count(x => x.Status == OrderStatus.WaitPay);
                vo.WaitGroupCount = orderQuery.Count(x => x.Status == OrderStatus.Paid && x.IsGroup);
                vo.WaitSendCount = orderQuery.Count(x => (x.Status == OrderStatus.Paid && !x.IsGroup) || (x.Status == OrderStatus.Group && x.IsGroup));
                vo.WaitGetCount = orderQuery.Count(x => x.Status == OrderStatus.Sent && x.ShippingType != ShippingType.Get);
                vo.WaitLiftCount = orderQuery.Count(x => x.Status == OrderStatus.Sent && x.ShippingType == ShippingType.Get);
                vo.WaitAppraiseCount = orderQuery.Count(x => x.Status == OrderStatus.Successed);
                vo.UserManagerName = userManagerName;
                vo.SourceUserQty = sourceUserQty;
            });
        }

        [AbpAuthorize]
        public async Task<PagedResultDto<UserFavoriteVO>> GetUserFavoritesAsync(PagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var query = _userFavoriteRepository.GetAll().Where(x => x.UserId == userId)
                .OrderByDescending(x => x.CreationTime);
            return await query.ToPagedResultDtoAsync<UserFavorite, UserFavoriteVO>(form, (f, vo) =>
            {
                vo.inItem = f.Item;
            });
        }

        public async Task<UserMiniVO> LoginAsync(UserAppLoginForm form)
        {
            var user = _userRepository.FirstOrDefault(x => x.PhoneNumber == form.UserPhoneNumber);
            if (user == null)
            {
                throw new UserFriendlyException("未找到该用户的注册信息，请先注册");
            }
            var userName = user.Name;
            var loginResult = await LogInManager.LoginAsync(userName, form.Password, null, false);
            if (loginResult.Result != AbpLoginResultType.Success)
            {
                throw CreateExceptionForFailedLoginAttempt(loginResult.Result, user.Name);
            }
            var result = user.ToVO<User, UserMiniVO>();
            result.Token = await CreateTokenAsync(user);
            return result;
        }


        [AbpAuthorize]
        public async Task<UserMiniVO> ModifyUserAsync(UserModifiedForm form)
        {
            var userId = AbpSession.GetUserId();
            var user = _userRepository.FirstOrDefault(x => x.Id == userId);
            if (user == null)
            {
                throw new UserFriendlyException("未找到该用户的注册信息，请先注册");
            }
            user.Name = form.Name;
            user.UserName = form.Name;
            user.Avatar = form.Avatar;
            user.Gender = form.Gender;
            await CurrentUnitOfWork.SaveChangesAsync();
            var result = user.ToVO<User, UserMiniVO>();
            result.Token = await CreateTokenAsync(user);
            return result;
        }

        [AbpAllowAnonymous]
        public async Task<UserMiniVO> LoginWithWechatAsync(WechatInfo info)
        {
            if(string.IsNullOrEmpty(info.OpenId))
            {
                throw new UserFriendlyException("OpenId为空 请重新登陆");
            }
            var user = await _userRepository.FirstOrDefaultAsync(x => x.OpenId == info.OpenId);
            
            var sourceUser = await UserManager.FindByIdAsync(info.SourceUserId ?? 0);
            if (user != null)
            {
                if (!user.IsActive)
                {
                    throw new UserFriendlyException("用户已禁用");
                }
            }
            else
            {
                user = new User
                {
                    Name = info.NickName,
                    Avatar = info.Avatar,
                    Gender = info.Gender,
                    IsActive = true,
                    UserName = info.NickName,
                    OpenId = info.OpenId,
                    Surname = info.NickName,
                    EmailAddress = "user@singleusermall.com",
                    Password = new PasswordHasher().HashPassword(User.DefaultPassword),
                    IsVip = false,
                    VipLevel = 0,
                    AgencyLevel = 0,
                    PhoneNumber = info.PhoneNumber,
                    Subscribes = info.Subscribes,
                    SourceUserId = info.SourceUserId,
                    GrandUserId = sourceUser?.SourceUserId,
                };
                var userId = await _userRepository.InsertAndGetIdAsync(user);
                await CurrentUnitOfWork.SaveChangesAsync();
                user = await _userRepository.FirstOrDefaultAsync(userId);
                OrderManager.CalculateDirectUserToNormalCanGetPoint(user, sourceUser);
                //升级到VIP
                if (sourceUser != null && !sourceUser.IsVip)
                {
                    sourceUser.IsVip = true;
                    sourceUser.VipLevel = 1;
                    var grandUser = _userRepository.FirstOrDefault(x => x.Id == sourceUser.SourceUserId);
                    OrderManager.CalculateDirectUserToVIPCanGetPoint(sourceUser, grandUser);
                }
                if (sourceUser != null)
                {
                    var active = _activeRepository.FirstOrDefault(x => x.Id == 2 && x.Enabled);
                    if(active != null)
                    {
                        var activeRecord = _activeRecordRepository.FirstOrDefault(x => x.UserId == sourceUser.Id && x.ActiveId == active.Id);
                        if(activeRecord != null)
                        {
                            if (activeRecord.CreationTime.Date < DateTime.Now.Date && user.IsVip && user.VipLevel == 2)
                            {
                                _activeRecordRepository.Delete(activeRecord);
                                _activeRecordRepository.Insert(new ActiveRecord() { User = sourceUser, ActiveId = active.Id, IsFinish = false, QueryTimes = 1 });
                            }
                            else if (!activeRecord.IsFinish)
                            {
                                activeRecord.QueryTimes += 1;
                            }
                        }
                        else
                        {
                            _activeRecordRepository.Insert(new ActiveRecord() { User = sourceUser, ActiveId = active.Id, IsFinish = false, QueryTimes = 1 });
                        }
                    }
                }
            }
            var result = user.ToVO<User, UserMiniVO>();
            result.Token = await CreateTokenAsync(user);
            return result;
        }

        [AbpAuthorize]
        public async Task ShareItem(ShareForm form)
        {
            var callUserId = AbpSession.GetUserId();
            if(callUserId == form.SourceUserId)
            {
                return;
            }
            var userId = form.SourceUserId;
            var active = _activeRepository.FirstOrDefault(x => x.Id == 1 && x.Enabled);
            if(active != null)
            {
                var activeRecord = _activeRecordRepository.FirstOrDefault(x => x.UserId == userId && x.ActiveId == active.Id);
                if (activeRecord != null)
                {
                    if (activeRecord.CreationTime.Date < DateTime.Now.Date)
                    {
                        _activeRecordRepository.Delete(activeRecord);
                        _activeRecordRepository.Insert(new ActiveRecord() { UserId = userId, ActiveId = active.Id, IsFinish = false, QueryTimes = 1, ItemIds = form.ItemId.ToString() });
                    }
                    else if (!activeRecord.IsFinish)
                    {
                        activeRecord.ItemIds += $",{form.ItemId}";
                        activeRecord.QueryTimes += 1;
                    }
                }
                else
                {
                    _activeRecordRepository.Insert(new ActiveRecord() { UserId = userId, ActiveId = active.Id, IsFinish = false, QueryTimes = 1, ItemIds=form.ItemId.ToString() });
                }
            }
        }


        [AbpAuthorize]
        public async Task LogoutAsync()
        {
            var userId = AbpSession.GetUserId();
            var user = await _userRepository.FirstOrDefaultAsync(userId);
            user.OpenId = null;
        }

        [AbpAllowAnonymous]
        public async Task<UserMiniVO> RegisterAsync(RegisterFrom form)
        {
            var valid = await UserManager.CheckCode(form.PhoneNumber, form.SmsCode);
            if (!valid)
            {
                throw new UserFriendlyException("手机号码或短信验证码不正确");
            }
            var user = _userRepository.FirstOrDefault(x => x.PhoneNumber == form.PhoneNumber);
            var sourceUser = await UserManager.FindByIdAsync(form.SourceUserId ?? 0);
            if (user != null)
            {
                if (!user.IsActive)
                {
                    throw new UserFriendlyException("用户已禁用");
                }
                throw new UserFriendlyException("您已经注册");
            }
            else
            {
                try
                {
                    user = new User
                    {
                        Name = form.PhoneNumber,
                        Avatar = "",
                        Gender = Authorization.Users.Gender.Male,
                        IsActive = true,
                        OpenId = form.OpenId,
                        Surname = form.PhoneNumber,
                        SourceUserId = form.SourceUserId,
                        GrandUserId = sourceUser?.SourceUserId,
                        EmailAddress = "user@singleusermall.com",
                        Password = new PasswordHasher().HashPassword(form.Password),
                        IsVip = false,
                        VipLevel = 0,
                        PhoneNumber = form.PhoneNumber,
                        UserIncome = User.UserIncomeStatus.MiddleIncome,
                        UserName = form.PhoneNumber,
                        AgencyLevel = 0
                    };
                    var userId = await _userRepository.InsertAndGetIdAsync(user);
                    await CurrentUnitOfWork.SaveChangesAsync();
                    user = await _userRepository.FirstOrDefaultAsync(userId);
                }

                catch (Exception e)
                {
                    throw new UserFriendlyException(e.Message);
                }
            }

            if (user != null)
            {
                var loginResult = await LogInManager.LoginAsync(user.UserName, form.Password, null, false);
                if (loginResult.Result != AbpLoginResultType.Success)
                {
                    throw CreateExceptionForFailedLoginAttempt(loginResult.Result, user.Name);
                }
            }

            var result = user.ToVO<User, UserMiniVO>();
            result.Token = await CreateTokenAsync(user);
            return result;
        }

        [AbpAuthorize]
        public async Task RegisterPromotionAsync(UserPromotionForm form)
        {
            var userId = AbpSession.GetUserId();
            var count = await _userPromotionRepository.CountAsync(x => x.UserId == userId && (x.Status == VerifyStatus.Audited || x.Status == VerifyStatus.WaitAudit));
            if (count > 0)
            {
                throw new UserFriendlyException("您已提交过申请，请等待系统审核");
            }
            var userPromotion = form.MapTo<UserPromotion>();
            userPromotion.UserId = userId;
            await _userPromotionRepository.InsertAsync(userPromotion);
        }

        [AbpAuthorize]
        public async Task RemoveUserCardAsync(SingleId<long> form)
        {
            await _userCardRepository.DeleteAsync(form.Id);
        }

        [AbpAuthorize]
        public async Task SaleAsync(UserSaleForm form)
        {
            var userId = AbpSession.GetUserId();
            var userSale = form.MapTo<UserSale>();
            userSale.UserId = userId;
            await _userSaleRepository.InsertAsync(userSale);
        }

        [AbpAuthorize]
        public async Task SaveUserCardAsync(UserCardForm form)
        {
            var userCard = await _userCardRepository.FirstOrDefaultAsync(form.Id);
            if (userCard == null)
            {
                userCard = form.MapTo<UserCard>();
                userCard.UserId = AbpSession.GetUserId();
                await _userCardRepository.InsertAsync(userCard);
            }
            else
            {
                userCard = form.MapTo(userCard);
                await _userCardRepository.UpdateAsync(userCard);
            }
        }

        [AbpAllowAnonymous]
        public async Task SendCodeAsync(SendCodeForm form)
        {
            var canSendCode = await UserManager.CheckCanSendCode(form.PhoneNumber, form.CheckDay);
            if (!canSendCode)
            {
                throw new UserFriendlyException($"旧的验证码可用，请填写{form.CheckDay}天收到的验证码");
            }
            var code = Functions.NewCode();
            var msg = string.Empty;
            var smsEntity = _smsRepository.FirstOrDefault(x => x.Id == 1);
            if (smsEntity != null)
            {
                smsEntity.Qty -= 1;
                if (smsEntity.Qty < 0)
                {
                    return;
                }
            }
            //sendCode
            var result = SmsContext.Instance.SendCode(form.PhoneNumber, code, ref msg);
            if (!result)
            {
                throw new UserFriendlyException(msg);
            }
            await UserManager.SetCode(form.PhoneNumber, code);
        }

        [AbpAllowAnonymous]
        public async Task SetPasswordAsync(SetPasswordForm form)
        {
            var user = await UserManager.FindUserWithPhoneAsync(form.PhoneNumber);
            var valid = await UserManager.CheckCode(form.PhoneNumber, form.SmsCode);
            if (!valid)
            {
                throw new UserFriendlyException("手机号码或短信验证码不正确");
            }
            if (user == null)
            {
                throw new UserFriendlyException("用户不存在");
            }
            user.Password = new PasswordHasher().HashPassword(form.Password);
        }

        [AbpAuthorize]
        public async Task SetPhoneNumberAsync(VerifyCodeForm form)
        {
            var user = await UserManager.FindByIdAsync(AbpSession.GetUserId());
            var valid = await UserManager.CheckCode(form.PhoneNumber, form.SmsCode);
            if (!valid)
            {
                throw new UserFriendlyException("手机号码或短信验证码不正确");
            }
            user.PhoneNumber = form.PhoneNumber;
        }

        [AbpAuthorize]
        public async Task SaveVerifiedAsync(VerifiedForm form)
        {
            var user = await UserManager.FindByIdAsync(AbpSession.GetUserId());
            user.TrueName = form.TrueName;
            user.UserIdCardNO = form.UserIdCardNO;
            user.IdCardImg = form.IdCardImg;
            CurrentUnitOfWork.SaveChanges();
        }

        public async Task<PagedResultDto<UserDividendsAppVO>> GetUserDividendAsync(PagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var query = _orderRepository.GetAll().Where(x => x.ShoppingCartType == ShoppingCarts.ShoppingCartType.TreeShopping && x.Status == OrderStatus.Paid && ((x.UserId == userId && !x.IsFriend) || (x.FriendUserId == userId && x.IsFriend)) && x.OrderDetails.FirstOrDefault().IsProfitStart).OrderByDescending(x => x.CreationTime);
            return await query.ToPagedResultDtoAsync<Order, UserDividendsAppVO>(form, (v, vo) =>
            {
                var orderDetail = v.OrderDetails.ToList().FirstOrDefault();
                vo.Name = orderDetail.ItemSpec?.Item?.Name;
                vo.Picture = orderDetail.ItemSpec?.Item?.Picture;
                vo.NumberPeriods = orderDetail.ItemSpec?.Item?.NumberPeriods;
                vo.Qty = orderDetail.Qty;
                vo.DailyProfit = orderDetail.DailyProfit;
                vo.Profit = orderDetail.Profit;
                vo.ProfitDateTime = orderDetail.ProfitDateTime;
            });
        }
    }
}